AliyunMqtt aliyunMqtt;                          // 实例化aliyunMqtt对象
uint8_t nowMqttConnectState = MqttDisconnected; // 当前MQTT的连接状态，初始化为MqttDisconnected

// 用于接收阿里云属性下发
// pH值是水中氢离子活度的负对数,pH值为7表示水是中性，大于7的水呈碱性，小于7的水呈酸性。 清洁天然水的pH值为6.5～8.5，pH值异常，表示水体受到污染。
float phMax = 8.5;
float phMin = 6.5;
float tuMax = 500; //正常262多

// 函数声明
void initWifi();
void initAlyMqtt();
void onMqttConnect(bool _sessionPresent);
void onMqttDisconnect(AsyncMqttClientDisconnectReason _reason);
void checkMqttAndReconnect();
void phMaxCallback(JsonVariant _data);
void phMinCallback(JsonVariant _data);
void tuMaxCallback(JsonVariant _data);

/**
 *初始化wifi
 */
void initWifi()
{
    // wifi相关
    WiFi.disconnect(true);                // 断开当前WIFI连接
    WiFi.mode(WIFI_STA);                  // 设置WIFI模式为STA模式
    WiFi.begin(wifiName, wifiPassword);   // 开始连接WIFI
    while (WL_CONNECTED != WiFi.status()) // 等待wifi连接
    {
        delay(500);
#if debugState
        debugSerial.print("."); //若未连接则一直打印.
#endif
    }
    debugSerial.println("\r\nwifi connect success!!!");
}

/**
 * 初始化aly_mqtt 放置setup函数中
 */
void initAlyMqtt()
{
    // aliyunMqtt.setDebug(debugSerial);                                      // 设置是否开启aliyunMqtt库中的打印，传入串口即开启打印
    aliyunMqtt.setDeviceCertificate(productKey, deviceName, deviceSecret); // 设置连接阿里云物联网平台的设备证书（也叫三元组）
    aliyunMqtt.mqttClient.setKeepAlive(mqttHeartbeatTime);                 // 设置心跳间隔时间
    aliyunMqtt.mqttClient.setMaxTopicLength(mqttPacketSize);               // 设置MQTT数据包大小
    aliyunMqtt.mqttClient.onConnect(onMqttConnect);                        // 设置MQTT连接事件的回调函数
    aliyunMqtt.mqttClient.onDisconnect(onMqttDisconnect);                  // 设置MQTT断开连接事件的回调函数
    aliyunMqtt.bindAttribute(PH_MAX_ID, phMaxCallback);                    // 绑定 PH最大值 属性以及设置接收回调函数
    aliyunMqtt.bindAttribute(PH_MIN_ID, phMinCallback);                    // 绑定 PH最小值 属性以及设置接收回调函数
    aliyunMqtt.bindAttribute(TU_MAX_ID, tuMaxCallback);                    // 绑定 浊度最大值 属性以及设置接收回调函数
    aliyunMqtt.mqttClient.connect();                                       // 连接MQTT服务器，连接结果在连接事件的回调函数或断开连接事件的回调函数中处理
    nowMqttConnectState = MqttConnecting;                                  // 当前MQTT的连接状态为连接中
}

/**
   函数功能：MQTT连接事件的回调函数
   参数1：[_sessionPresent] [bool] 会话是否存在
   返回值：无
   注意事项：无
*/
void onMqttConnect(bool _sessionPresent)
{
#if debugState
    debugSerial.println("阿里云物联网MQTT服务器已连接，会话存在状态为：" + String(_sessionPresent));
#endif
    nowMqttConnectState = MqttConnected;    // 当前MQTT的连接状态为已连接
    aliyunMqtt.subscribeAttributeSetting(); // 订阅设备属性设置主题
}

/**
   函数功能：MQTT断开连接事件的回调函数
   参数1：[_reason] [AsyncMqttClientDisconnectReason] MQTT断开连接的原因，在AsyncMqttClientDisconnectReason枚举中查看
   返回值：无
   注意事项：无
*/
void onMqttDisconnect(AsyncMqttClientDisconnectReason _reason)
{
#if debugState
    debugSerial.println("阿里云物联网MQTT服务器已断开连接！原因为：" + String(uint8_t(_reason)));
#endif
    nowMqttConnectState = MqttDisconnected; // 当前MQTT的连接状态为已断开连接
}

/**
   函数功能：检查MQTT和重连
   参数：无
   返回值：无
   注意事项：无
*/
void checkMqttAndReconnect()
{
    static uint8_t mqttConnectStateMachine = 0; // MQTT连接的状态机
    static uint32_t nowTime = 0;                // 检查时间
    switch (mqttConnectStateMachine)
    {
    // 检查MQTT的连接状态
    case 0:
    {
        if (MqttDisconnected == nowMqttConnectState)
        {                                           // 如果当前MQTT的连接状态为已断开连接
            aliyunMqtt.mqttClient.disconnect(true); // 断开之前的连接
            aliyunMqtt.mqttClient.connect();        // 连接MQTT服务器，连接结果在连接事件的回调函数或断开连接事件的回调函数中处理
            mqttConnectStateMachine = 1;            // MQTT连接中，状态机=1，重连中
            nowTime = millis();                     // 更新当前时间
#if debugState
            debugSerial.println("阿里云MQTT服务器已断开连接！开始尝试重连中......");
#endif
        }
    }
    break;
    // MQTT重连中
    case 1:
    {
        if (MqttConnected == nowMqttConnectState || millis() - nowTime > ckeckMqttConnectTime)
        {                                // 如果当前MQTT的连接状态为已连接或者超过重连时间
            mqttConnectStateMachine = 0; // 状态机=0，回到检查中
        }
    }
    break;

    default:
        break;
    }
}

/**
   函数功能：上报多种类型属性
   参数：无
   返回值：无
   注意事项：无
*/
void reportMultipleAttribute(String data)
{
    if (nowMqttConnectState == MqttConnected)
    {
        uint16_t result = aliyunMqtt.sendMultipleAttributeData(data); // 发送数据到云平台
#if debugState
        debugSerial.println("上报多种类型属性，发送数据为：[" + String(data) + "]，发送状态为：" + String(result ? "已发送，ID为：" + String(result) : "失败！"));
#endif
    }
}

// 属性下发
void phMaxCallback(JsonVariant _data)
{
    phMax = _data[PH_MAX_ID]; // 获取最大ph值
#if debugState
    debugSerial.println("PH最大值为：" + String(phMax));
#endif
}
void phMinCallback(JsonVariant _data)
{
    phMin = _data[PH_MIN_ID]; // 获取最小ph值
#if debugState
    debugSerial.println("PH最小值为：" + String(phMin));
#endif
}
void tuMaxCallback(JsonVariant _data)
{
    tuMax = _data[TU_MAX_ID]; // 获取浊度
#if debugState
    debugSerial.println("浊度最大值为：" + String(tuMax));
#endif
}